// /////////////////////////////////////////////////////////////////////////////
//
// Name:            SerializedAttributes.cpp
// Author:          Michael Bartsch (ZCCdark203)
//
// Desc :           The SerializaedAttributes class describes a FIFO collection
//                  of serialized attributes. This class provides various
//                  methods to manage these attributes.
//
// License:         Copyright (C) 2009 Michael Bartsch and Contributors
//
//                  This program is free software: you can redistribute it
//                  and/or modify it under the terms of the zlib/libpng License.
//                  See main.cpp for conditions of distribution and use.
//
// /////////////////////////////////////////////////////////////////////////////

// Include files
#include "SerializedAttributes.h"
#include "SerializedAttributesImpl.h"


// SerializedAttributes class
// SerializedAttributes constructor.
SerializedAttributes::SerializedAttributes()
{
}

// SerializedAttributes deconstructor.
SerializedAttributes::~SerializedAttributes()
{
    removeAttributes();
}

// Returns whether there are attributes in the internal queue.
bool SerializedAttributes::isEmpty() const
{
    return mQueue.empty();
}

// Moves all attributes from this object to the given object.
void SerializedAttributes::moveAttributesTo(SerializedAttributes *attributes)
{
    // Remove attributes from the receiver.
    attributes->removeAttributes();

    // Move our attributes to the receiver.
    while(!mQueue.empty())
      attributes->pushAttribute(pullAttribute());
}

// Serializes this object.
bool SerializedAttributes::onSerialization(SerializedAttributes *attributes)
{
    moveAttributesTo(attributes);
    return true;
}

// Deserializes this object.
bool SerializedAttributes::onDeserialization(SerializedAttributes *attributes)
{
    attributes->moveAttributesTo(this);
    return true;
}

// Pulls the first attribute from the internal attribute queue.
SerializedAttribute* SerializedAttributes::pullAttribute()
{
    // Try to retrieve an attribute from the queue.
    if(!mQueue.empty())
    {
       SerializedAttribute *attribute = mQueue.front();
       mQueue.pop();

       return attribute;
    }

    // We could not retrieve an attribute.
    return NULL;
}

// Pulls an attribute from the queue and interprete it as an aabbox3df object.
aabbox3df SerializedAttributes::pullAabbox3df()
{
    SerializedAttribute *attribute = pullAttribute();

    if(attribute != NULL)
    {
       aabbox3df value = attribute->getAabbox3df();
       attribute->drop();

       return value;
    }

    return aabbox3df();
}

// RPulls an attribute from the queue and interprete it as an aabbox3di object.
aabbox3di SerializedAttributes::pullAabbox3di()
{
    SerializedAttribute *attribute = pullAttribute();

    if(attribute != NULL)
    {
       aabbox3di value = attribute->getAabbox3di();
       attribute->drop();

       return value;
    }

    return aabbox3di();
}

// Pulls an attribute from the queue and interprete it as a boolean value.
bool SerializedAttributes::pullBool()
{
    SerializedAttribute *attribute = pullAttribute();

    if(attribute != NULL)
    {
       bool value = attribute->getBool();
       attribute->drop();

       return value;
    }

    return false;
}

// Pulls an attribute from the queue and interprete it as a SColor object.
SColor SerializedAttributes::pullColor()
{
    SerializedAttribute *attribute = pullAttribute();

    if(attribute != NULL)
    {
       SColor value = attribute->getColor();
       attribute->drop();

       return value;
    }

    return SColor();
}

// Pulls an attribute from the queue and interprete it as a SColorf object.
SColorf SerializedAttributes::pullColorf()
{
    SerializedAttribute *attribute = pullAttribute();

    if(attribute != NULL)
    {
       SColorf value = attribute->getColorf();
       attribute->drop();

       return value;
    }

    return SColorf();
}

// Pulls an attribute from the queue and interprete it as a dimension2df object.
dimension2df SerializedAttributes::pullDimension2df()
{
    SerializedAttribute *attribute = pullAttribute();

    if(attribute != NULL)
    {
       dimension2df value = attribute->getDimension2df();
       attribute->drop();

       return value;
    }

    return dimension2df();
}

// Pulls an attribute from the queue and interprete it as a dimension2di object.
dimension2di SerializedAttributes::pullDimension2di()
{
    SerializedAttribute *attribute = pullAttribute();

    if(attribute != NULL)
    {
       dimension2di value = attribute->getDimension2di();
       attribute->drop();

       return value;
    }

    return dimension2di();
}

// Pulls an attribute from the queue and interprete it as a float value.
f32 SerializedAttributes::pullFloat()
{
    SerializedAttribute *attribute = pullAttribute();

    if(attribute != NULL)
    {
       f32 value = attribute->getFloat();
       attribute->drop();

       return value;
    }

    return 0.0f;
}

// Pulls an attribute from the queue and interprete it as an integer value.
s32 SerializedAttributes::pullInt()
{
    SerializedAttribute *attribute = pullAttribute();

    if(attribute != NULL)
    {
       s32 value = attribute->getInt();
       attribute->drop();

       return value;
    }

    return 0;
}

// Pulls an attribute from the queue and interprete it as a line2df object.
line2df SerializedAttributes::pullLine2df()
{
    SerializedAttribute *attribute = pullAttribute();

    if(attribute != NULL)
    {
       line2df value = attribute->getLine2df();
       attribute->drop();

       return value;
    }

    return line2df();
}

// Pulls an attribute from the queue and interprete it as a line2di object.
line2di SerializedAttributes::pullLine2di()
{
    SerializedAttribute *attribute = pullAttribute();

    if(attribute != NULL)
    {
       line2di value = attribute->getLine2di();
       attribute->drop();

       return value;
    }

    return line2di();
}

// Pulls an attribute from the queue and interprete it as a line3df object.
line3df SerializedAttributes::pullLine3df()
{
    SerializedAttribute *attribute = pullAttribute();

    if(attribute != NULL)
    {
       line3df value = attribute->getLine3df();
       attribute->drop();

       return value;
    }

    return line3df();
}

// Pulls an attribute from the queue and interprete it as a line3di object.
line3di SerializedAttributes::pullLine3di()
{
    SerializedAttribute *attribute = pullAttribute();

    if(attribute != NULL)
    {
       line3di value = attribute->getLine3di();
       attribute->drop();

       return value;
    }

    return line3di();
}

// Pulls an attribute from the queue and interprete it as a Serializable object.
Serializable* SerializedAttributes::pullObject()
{
    SerializedAttribute *attribute = pullAttribute();

    if(attribute != NULL)
    {
       Serializable *object = attribute->getObject();
       attribute->drop();

       return object;
    }

    return NULL;
}

// Pulls an attribute from the queue and interprete it as a plane3df object.
plane3df SerializedAttributes::pullPlane3df()
{
    SerializedAttribute *attribute = pullAttribute();

    if(attribute != NULL)
    {
       plane3df value = attribute->getPlane3df();
       attribute->drop();

       return value;
    }

    return plane3df();
}

// Pulls an attribute from the queue and interprete it as a plane3di object.
plane3di SerializedAttributes::pullPlane3di()
{
    SerializedAttribute *attribute = pullAttribute();

    if(attribute != NULL)
    {
       plane3di value = attribute->getPlane3di();
       attribute->drop();

       return value;
    }

    return plane3di();
}

// Pulls an attribute from the queue and interprete it as a quaternion object.
quaternion SerializedAttributes::pullQuaternion()
{
    SerializedAttribute *attribute = pullAttribute();

    if(attribute != NULL)
    {
       quaternion value = attribute->getQuaternion();
       attribute->drop();

       return value;
    }

    return quaternion();
}

// Pulls an attribute from the queue and interprete it as a rect<s32> object.
rect<s32> SerializedAttributes::pullRect()
{
    SerializedAttribute *attribute = pullAttribute();

    if(attribute != NULL)
    {
       rect<s32> value = attribute->getRect();
       attribute->drop();

       return value;
    }

    return rect<s32>();
}

// Pulls an attribute from the queue and interprete it as a string.
std::string SerializedAttributes::pullString()
{
    SerializedAttribute *attribute = pullAttribute();

    if(attribute != NULL)
    {
       std::string value = attribute->getString();
       attribute->drop();

       return value;
    }

    return "";
}

// Pulls an attribute from the queue and interprete it as a wide string.
stringw SerializedAttributes::pullStringW()
{
    SerializedAttribute *attribute = pullAttribute();

    if(attribute != NULL)
    {
       stringw value = attribute->getStringW();
       attribute->drop();

       return value;
    }

    return L"";
}

// Pulls an attribute from the queue and interprete it as a vector2df object.
vector2df SerializedAttributes::pullVector2df()
{
    SerializedAttribute *attribute = pullAttribute();

    if(attribute != NULL)
    {
       vector2df value = attribute->getVector2df();
       attribute->drop();

       return value;
    }

    return vector2df();
}

// Pulls an attribute from the queue and interprete it as a vector2di object.
vector2di SerializedAttributes::pullVector2di()
{
    SerializedAttribute *attribute = pullAttribute();

    if(attribute != NULL)
    {
       vector2di value = attribute->getVector2di();
       attribute->drop();

       return value;
    }

    return vector2di();
}

// Pulls an attribute from the queue and interprete it as a vector3df object
vector3df SerializedAttributes::pullVector3df()
{
    SerializedAttribute *attribute = pullAttribute();

    if(attribute != NULL)
    {
       vector3df value = attribute->getVector3df();
       attribute->drop();

       return value;
    }

    return vector3df();
}

// Pulls an attribute from the queue and interprete it as a vector3di object.
vector3di SerializedAttributes::pullVector3di()
{
    SerializedAttribute *attribute = pullAttribute();

    if(attribute != NULL)
    {
       vector3di value = attribute->getVector3di();
       attribute->drop();

       return value;
    }

    return vector3di();
}

// Pushes a new attribute into the internal attribute queue.
void SerializedAttributes::pushAttribute(SerializedAttribute *attribute)
{
    attribute->grab();
    mQueue.push(attribute);
}

// Pushes an attribute into the queue as an aabbox3df object.
void SerializedAttributes::pushAabbox3df(const std::string &name, const aabbox3df &value)
{
    SerializedAabbox3d *attribute = new SerializedAabbox3d(name, value);
    pushAttribute(attribute);
    attribute->drop();
}

// Pushes an attribute into the queue as an aabbox3di object.
void SerializedAttributes::pushAabbox3di(const std::string &name, const aabbox3di &value)
{
    SerializedAabbox3d *attribute = new SerializedAabbox3d(name, value);
    pushAttribute(attribute);
    attribute->drop();
}

// Pushes an attribute into the queue as a boolean value.
void SerializedAttributes::pushBool(const std::string &name, bool value)
{
    SerializedBool *attribute = new SerializedBool(name, value);
    pushAttribute(attribute);
    attribute->drop();
}

// Pushes an attribute into the queue as a SColor object.
void SerializedAttributes::pushColor(const std::string &name, const SColor &value)
{
    SerializedColor *attribute = new SerializedColor(name, value);
    pushAttribute(attribute);
    attribute->drop();
}

// Pushes an attribute into the queue as a SColorf object.
void SerializedAttributes::pushColorf(const std::string &name, const SColorf &value)
{
    SerializedColor *attribute = new SerializedColor(name, value);
    pushAttribute(attribute);
    attribute->drop();
}

// Pushes an attribute into the queue as a dimension2df object.
void SerializedAttributes::pushDimension2df(const std::string &name, const dimension2df &value)
{
    SerializedDimension2d *attribute = new SerializedDimension2d(name, value);
    pushAttribute(attribute);
    attribute->drop();
}

// Pushes an attribute into the queue as a dimension2di object.
void SerializedAttributes::pushDimension2di(const std::string &name, const dimension2di &value)
{
    SerializedDimension2d *attribute = new SerializedDimension2d(name, value);
    pushAttribute(attribute);
    attribute->drop();
}

// Pushes an attribute into the queue as a float value.
void SerializedAttributes::pushFloat(const std::string &name, f32 value)
{
    SerializedNumber *attribute = new SerializedNumber(name, value);
    pushAttribute(attribute);
    attribute->drop();
}

// Pushes an attribute into the queue as an integer value.
void SerializedAttributes::pushInt(const std::string &name, s32 value)
{
    SerializedNumber *attribute = new SerializedNumber(name, value);
    pushAttribute(attribute);
    attribute->drop();
}

// Pushes an attribute into the queue as a line2df object.
void SerializedAttributes::pushLine2df(const std::string &name, const line2df &value)
{
    SerializedLine2d *attribute = new SerializedLine2d(name, value);
    pushAttribute(attribute);
    attribute->drop();
}

// Pushes an attribute into the queue as a line2di object.
void SerializedAttributes::pushLine2di(const std::string &name, const line2di &value)
{
    SerializedLine2d *attribute = new SerializedLine2d(name, value);
    pushAttribute(attribute);
    attribute->drop();
}

// Pushes an attribute into the queue as a line3df object.
void SerializedAttributes::pushLine3df(const std::string &name, const line3df &value)
{
    SerializedLine3d *attribute = new SerializedLine3d(name, value);
    pushAttribute(attribute);
    attribute->drop();
}

// Pushes an attribute into the queue as a line3di object.
void SerializedAttributes::pushLine3di(const std::string &name, const line3di &value)
{
    SerializedLine3d *attribute = new SerializedLine3d(name, value);
    pushAttribute(attribute);
    attribute->drop();
}

// Pushes an attribute into the queue as a Serializable object.
void SerializedAttributes::pushObject(const std::string &name, Serializable *object)
{
    SerializedObject *attribute = new SerializedObject(name, object);
    pushAttribute(attribute);
    attribute->drop();
}

// Pushes an attribute into the queue as a plane3df object.
void SerializedAttributes::pushPlane3df(const std::string &name, const plane3df &value)
{
    SerializedPlane3d *attribute = new SerializedPlane3d(name, value);
    pushAttribute(attribute);
    attribute->drop();
}

// Pushes an attribute into the queue as a plane3di object.
void SerializedAttributes::pushPlane3di(const std::string &name, const plane3di &value)
{
    SerializedPlane3d *attribute = new SerializedPlane3d(name, value);
    pushAttribute(attribute);
    attribute->drop();
}

// Pushes an attribute into the queue as a quaternion object.
void SerializedAttributes::pushQuaternion(const std::string &name, const quaternion &value)
{
    SerializedQuaternion *attribute = new SerializedQuaternion(name, value);
    pushAttribute(attribute);
    attribute->drop();
}

// Pushes an attribute into the queue as a rect<s32> object.
void SerializedAttributes::pushRect(const std::string &name, const rect<s32> &value)
{
    SerializedRect *attribute = new SerializedRect(name, value);
    pushAttribute(attribute);
    attribute->drop();
}

// Pushes an attribute into the queue as a string.
void SerializedAttributes::pushString(const std::string &name, const std::string &value)
{
    SerializedString *attribute = new SerializedString(name, value);
    pushAttribute(attribute);
    attribute->drop();
}

// Pushes an attribute into the queue as a wide string.
void SerializedAttributes::pushStringW(const std::string &name, const stringw &value)
{
    SerializedString *attribute = new SerializedString(name, value);
    pushAttribute(attribute);
    attribute->drop();
}

// Pushes an attribute into the queue as a vector2df object.
void SerializedAttributes::pushVector2df(const std::string &name, const vector2df &value)
{
    SerializedVector2d *attribute = new SerializedVector2d(name, value);
    pushAttribute(attribute);
    attribute->drop();
}

// Pushes an attribute into the queue as a vector2di object.
void SerializedAttributes::pushVector2di(const std::string &name, const vector2di &value)
{
    SerializedVector2d *attribute = new SerializedVector2d(name, value);
    pushAttribute(attribute);
    attribute->drop();
}

// Pushes an attribute into the queue as a vector3df object.
void SerializedAttributes::pushVector3df(const std::string &name, const vector3df &value)
{
    SerializedVector3d *attribute = new SerializedVector3d(name, value);
    pushAttribute(attribute);
    attribute->drop();
}

// Pushes an attribute into the queue as a vector3di object.
void SerializedAttributes::pushVector3di(const std::string &name, const vector3di &value)
{
    SerializedVector3d *attribute = new SerializedVector3d(name, value);
    pushAttribute(attribute);
    attribute->drop();
}

// Removes all attributes from the internal attribute queue.
void SerializedAttributes::removeAttributes()
{
    while(!mQueue.empty())
    {
        mQueue.front()->drop();
        mQueue.pop();
    }
}

// End of File
